﻿<!DOCTYPE html>
<html>

<head>
	<meta charset=utf-8>
	<title>Setting the custom loader</title>
	<link href="../base.css" rel="stylesheet" type="text/css" />
</head>

<body>
	<div class="main">
		<h1>Setting the custom loader</h1>
		
		<h2>Overview</h2>
		<p>
Effekseer supports basic loading, but it is not designed to be loadable from other game engine packages.
So add a loader class and extend the file loading method.
		</p>

		<h2>Loading the effect file</h2>
		<p>
In order to load the effect file, inherit "::Effekseer::EffectLoader" class and set it with "::Effekseer::Manager::SetEffectLoader".
Actually, I will write a class to load from a normal file system. Allocate the memory with the Load function and free the memory with the Unload function.
		</p>
<pre>
<code>
class EffectLoader : public ::Effekseer::EffectLoader {
public:
	EffectLoader() {}
	virtual ~EffectLoader() {}
	bool Load( const EFK_CHAR* path, void*& data, int32_t& size );
	void Unload( void* data, int32_t size );
};

bool EffectLoader::Load( const EFK_CHAR* path, void*& data, int32_t& size ) {
	data = NULL;
	size = 0;

	FILE* fp = _wfopen( (const wchar_t*)path, L"rb" );
	if( fp == NULL ) return false;

	fseek( fp, 0, SEEK_END );
	size = (int32_t)ftell( fp );
	data = new uint8_t[size];
	fseek( fp, 0, SEEK_SET );
	fread( data, 1, size, fp );
	fclose( fp );
	
	return true;
}

void EffectLoader::Unload( void* data, int32_t size ) {
	if( data != NULL ) delete [] data;
}

// Specify loader
manager->SetEffectLoader( new EffectLoader() );
</code>
</pre>

		<h2>Loading a texture file</h2>
		<p>
In order to load the image file, inherit "::Effekseer::TextureLoader" class and set it with "::Effekseer::Manager::SetTextureLoader".
Actually, I will write a class to load from a normal file system with DirectX9.
Load a image with the Load function and release the image with the Unload function.
		</p>

<pre>
<code>
class TextureLoader : public ::Effekseer::TextureLoader {
private:
	::EffekseerRenderer::Renderer*	m_renderer;

public:
	TextureLoader( ::EffekseerRenderer::Renderer* renderer ) { m_renderer = renderer; }
	virtual ~TextureLoader() {}
	void* Load( const EFK_CHAR* path );
	void Unload( void* data );
};

void* TextureLoader::Load( const EFK_CHAR* path, ::Effekseer::TextureType textureType ) {
	FILE* fp_texture = _wfopen( (const wchar_t *)path, L"rb" );

	if( fp_texture != NULL ) {
		IDirect3DTexture9* texture = NULL;

		fseek( fp_texture, 0, SEEK_END );
		size_t size_texture = ftell( fp_texture );
		char* data_texture = new char[size_texture];
		fseek( fp_texture, 0, SEEK_SET );
		fread( data_texture, 1, size_texture, fp_texture );
		fclose( fp_texture );

		D3DXCreateTextureFromFileInMemory( m_renderer->GetDevice(), data_texture, size_texture, &texture );

		delete [] data_texture;

		return (void*)texture;
	}

	return NULL;
}

void TextureLoader::Unload( void* data ) {
	if( data != NULL ) {
		IDirect3DTexture9* texture = (IDirect3DTexture9*)data;
		texture->Release();
	}
}

// Specify the loader
manager->SetTextureLoader( new TextureLoader() );
</code>
</pre>

		<h2>The problem of relative path</h2>
		<p>
In the case of image file, a path provided is a relative path to texture file when an effect is saved with the tool.
In many cases, when loading an effect file, you need to load the texture of the relative path position from the effect file.
As an example, I will describe an example.
Make the TextureLoader class have a file path and rewrite the path before executing "::Effekseer::Create::Effect::Create".
		</p>

<pre>
<code>
class TextureLoader : public ::Effekseer::TextureLoader {
private:
	::EffekseerRenderer::Renderer*	m_renderer;

public:
	TextureLoader( ::EffekseerRenderer::Renderer* renderer ) { m_renderer = renderer; }
	virtual ~TextureLoader() {}
	void* Load( const EFK_CHAR* path );
	void Unload( void* data );

	// Root path when loading
	std::wstring RootPath;
};

void* TextureLoader::Load( const EFK_CHAR* path, ::Effekseer::TextureType textureType ) {

	wchar_t dst[260];
	
	// A function for combining file pathes
	Combine( RootPath.c_str(), (const wchar_t *)path, dst, 260 );

	FILE* fp_texture = _wfopen( (const wchar_t *)dst, L"rb" );

	if( fp_texture != NULL ) {
		IDirect3DTexture9* texture = NULL;

		fseek( fp_texture, 0, SEEK_END );
		size_t size_texture = ftell( fp_texture );
		char* data_texture = new char[size_texture];
		fseek( fp_texture, 0, SEEK_SET );
		fread( data_texture, 1, size_texture, fp_texture );
		fclose( fp_texture );

		D3DXCreateTextureFromFileInMemory( m_renderer->GetDevice(), data_texture, size_texture, &texture );

		delete [] data_texture;

		return (void*)texture;
	}

	return NULL;
}

void TextureLoader::Unload( void* data ) {
	if( data != NULL ) {
		IDirect3DTexture9* texture = (IDirect3DTexture9*)data;
		texture->Release();
	}
}

// Specify the loader
manager->SetTextureLoader( new TextureLoader() );

// Specify it before executing Create.
((TextureLoader*)manager->GetTextureLoader())->RootPath = std::wstring( Path );
::Effekseer::Effect* effect = ::Effekseer::Effect::Create( manager, Path );
</code>
</pre>

	</div>
</body>

</html>